package com.dilean.spring.jpa;

import java.util.Properties;

import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import com.dilean.common.CommonConstans;

@Configuration
@EnableTransactionManagement
public class PersistenceJpaConfig
{
    private static final Log log = LogFactory.getLog(PersistenceJpaConfig.class);
    
    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory()
    {
        LocalContainerEntityManagerFactoryBean emFactory = new LocalContainerEntityManagerFactoryBean();
        emFactory.setDataSource(dataSource());
        emFactory.setPackagesToScan(CommonConstans.JPA_IMPL_PACHAGE);
        
        JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        emFactory.setJpaVendorAdapter(vendorAdapter);
        
        final Properties jpaProperties = new Properties();
        
        try
        {
            jpaProperties.load(PersistenceJpaConfig.class.getResourceAsStream("jpa.properties"));
        }
        catch(Exception ex)
        {
            throw new RuntimeException("Cannot load jpa.properties", ex);
        }
        
        emFactory.setJpaProperties(jpaProperties);
        
        if(log.isDebugEnabled())
            log.debug(jpaProperties);
        
        return emFactory;
    }

    @Bean
    public DataSource dataSource()
    {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        final Properties dbProperties = new Properties();
      
        try
        {
            dbProperties.load(PersistenceJpaConfig.class.getResourceAsStream("db.properties"));
        }
        catch(Exception ex)
        {
            throw new RuntimeException("Cannot load db.properties", ex);
        }
        
        dataSource.setDriverClassName(dbProperties.getProperty("db.driver.class"));
        dataSource.setUrl(dbProperties.getProperty("db.url"));
        dataSource.setUsername(dbProperties.getProperty("db.user"));
        dataSource.setPassword(dbProperties.getProperty("db.password"));
        
        if(log.isDebugEnabled())
            log.debug(dbProperties);
        
        return dataSource;
    }

    @Bean
    public PlatformTransactionManager transactionManager(EntityManagerFactory emf)
    {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(emf);

        return transactionManager;
    }

    @Bean
    public PersistenceExceptionTranslationPostProcessor exceptionTranslation()
    {
        return new PersistenceExceptionTranslationPostProcessor();
    }
    
    @Bean
    public JdbcTemplate getJdbcTemplate(DataSource dataSource)
    {
    	return new JdbcTemplate(dataSource);
    }
}